package cn.topcodes.tcsf.admin.service.ops;

import cn.topcode.unicorn.utils.StringUtil;
import cn.topcode.unicorn.utils.http.HttpUtil;
import cn.topcodes.tcsf.admin.service.ops.proto.StatusReportRequest;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Created by Unicorn on 2018/6/26.
 */
@Component
public class SysUpgradeService {

    private Logger logger = LoggerFactory.getLogger(SysUpgradeService.class);

    public static final String URL_CHECK_VERSION = "http://%s:%d/api/server/check-version?no=%s&version=%s";

    @Autowired
    private OpsConnectedListener opsConnectedListener;

    @Autowired
    private OpsService opsService;

    private boolean isUpgrade = false;

    public RespCheckVersion checkVersion() {
        if(!opsService.isEnable()) {
            return null;
        }
        String version = opsConnectedListener.getVersion();
        if(StringUtil.isBlank(version)) {
            return null;
        }
        String no = opsService.getNo();
        String opsServerHost = opsService.getOpsServerHost();
        Integer opsServerHttpPort = opsService.getOpsServerHttpPort();
        String url = String.format(URL_CHECK_VERSION, opsServerHost, opsServerHttpPort, no, version);
        RespCheckVersionResult result = HttpUtil.getJson(url, RespCheckVersionResult.class);
        if(result == null || !"OK".equals(result.getCode())) {
            return null;
        }
        return result.getBody();
    }

    private boolean downloadWar(String version, String url) {
        String contextPath = "ROOT";
        if(StringUtil.isNotBlank(opsConnectedListener.getContextPath())) {
            contextPath = opsConnectedListener.getContextPath();
        }
        opsService.submitServerLog("开始下载版本" + version + "二进制包");
        String targetFile = System.getProperty("catalina.base") + "/webapps." + version + "/" + contextPath + ".war";
        String result = HttpUtil.download(url, targetFile);
        if(result == null) {
            opsService.submitServerLog("下载版本" + version + "二进制包失败");
        }else {
            opsService.submitServerLog("下载版本" + version + "二进制包完成");
        }
        return result != null;
    }

    private boolean runUpgradeShell(String oldVersion, String newVersion, boolean os) {
        logger.warn("执行升级脚本 >>>>>>>>>>>>>>");
        opsService.submitServerLog("执行升级至版本" + newVersion + "的批处理脚本");

        String catalinaBase = System.getProperty("catalina.base");
        String oldVersionFolder = catalinaBase + "/webapps." + oldVersion;
        String newVersionFolder = catalinaBase + "/webapps." + newVersion;
        String cmd;

        try {
            if(os) {
                FileUtils.copyFile(new File(this.getClass().getResource("/shell/upgrade.bat").getPath()),
                        new File(catalinaBase + "/bin/upgrade.bat"));
            }
            cmd = os ? "cmd.exe /c start " + catalinaBase + "/bin/upgrade.bat"
                    + " " + catalinaBase + " " + oldVersionFolder + " " + newVersionFolder
                    + " " + oldVersion + " " + newVersion
                    : "sh " + this.getClass().getResource("/shell/upgrade.sh").getPath()
                    + " " + catalinaBase + " " + oldVersionFolder + " " + newVersionFolder
                     + " " + oldVersion + " " + newVersion;
            Process ps = Runtime.getRuntime().exec(cmd);
            BufferedReader br = new BufferedReader(new InputStreamReader(ps.getInputStream(), "UTF-8"));//注意中文编码问题
            String line;
            while ((line = br.readLine()) != null) {
                logger.warn("升级脚本输出 >>> " + line);
                opsService.submitServerLog("升级脚本输出 >>> " + line);
            }
            br.close();
        } catch (IOException e) {
            logger.error("执行升级脚本失败", e);
            opsService.submitServerLog("执行升级脚本失败，异常信息：" + e.getMessage());
            return false;
        }
        opsService.submitServerLog("版本升级完成");
        return true;
    }

    public void upgrade(String version, String url) {
        if(!opsService.isEnable()) {
            throw new IllegalStateException("无法升级！未启动Ops服务");
        }
        if(isUpgrade) {
            return;
        }
        isUpgrade = true;
        opsService.setStatus(StatusReportRequest.STATUS_UPGRADE);
        opsService.submitServerLog("开始升级版本为" + version);
        opsService.reportStatus();
        new Thread(new Runnable() {
            @Override
            public void run() {
                if(downloadWar(version, url)) {
                    if(runUpgradeShell(opsConnectedListener.getVersion(), version, isWindows())) {
                    }else {
                        opsService.setStatus(StatusReportRequest.STATUS_RUNNING);
                        opsService.reportStatus();
                    }
                }else {
                    opsService.setStatus(StatusReportRequest.STATUS_RUNNING);
                    opsService.reportStatus();
                }
                isUpgrade = false;
            }
        }).start();
    }

    public boolean isWindows() {
        return System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1;
    }
}
